#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <memory>
#include <list>

// 此例子是考虑线程安全的

// 抽象观察者类
class IObserver {
    public:
    IObserver() {}
    virtual ~IObserver() {}

    public:
    virtual void Update(int data) = 0;
};

// 抽象被观察者类
class ISubject {
public:
    ISubject() {}
    virtual ~ISubject() {}

public:
    virtual void Subscribe(std::shared_ptr<IObserver> observer) = 0; // 观察者订阅事件
    virtual void UnSubscribe(std::shared_ptr<IObserver> observer) = 0; // 观察者取消事件的订阅
    virtual void Notify(int data) = 0; // 通知已订阅指定事件的观察者

public:
    std::list<std::weak_ptr<IObserver>> observers_;   // 存放所有已订阅的observer
};


// 具体观察者类
class ConcreteObserver : public IObserver {
public:
    ConcreteObserver(const std::string& name):name_(name) {}
    virtual ~ConcreteObserver() {}

public:
    virtual void Update(int data) {
        std::cout << "observer [" << name_ << "] updated -> " << data << std::endl;
    }
private:
    std::string name_;
};

// 具体被观察者类
class ConCreteSubject : public ISubject {
public:
    ConCreteSubject() {}
    virtual ~ConCreteSubject() {}

public:
    virtual void Subscribe(std::shared_ptr<IObserver> observer) {
        observers_.push_back(observer);
    }
    virtual void UnSubscribe(std::shared_ptr<IObserver> observer) {
        observers_.erase(std::remove_if(observers_.begin(),observers_.end(),
                        [&observer](std::weak_ptr<IObserver> obj) {
                         std::shared_ptr<IObserver> tmp = obj.lock();
                         if (tmp != nullptr) {
                            return tmp == observer;
                         }
                         else {
                            return false;
                         }
                        }),
                        observers_.end());

    }
    virtual void Notify(int data) {
        for(auto it = observers_.begin();it != observers_.end();it++) {
            std::shared_ptr<IObserver> ps = it->lock();
            // weak_ptr提升为shared_ptr
            // 判断对象是否还存活
            if (ps != nullptr) {
                ps->Update(data);
            }
            else {
                it = observers_.erase(it);
            }
        }
    }
};


int main() {
    std::cout << "hello observer pattern!!!" << std::endl;
    // 构造3个观察者对象
    std::shared_ptr<IObserver> observer1(new ConcreteObserver("observer1"));
    std::shared_ptr<IObserver> observer2(new ConcreteObserver("observer2"));
    std::shared_ptr<IObserver> observer3(new ConcreteObserver("observer3"));

    // 构造一个主题对象
    ConCreteSubject subject;
    
    // 为观察者订阅事件
    subject.Subscribe(observer1);
    subject.Subscribe(observer2);
    subject.Subscribe(observer3);

    // 通知订阅事件的观察者
    subject.Notify(10);
 
    // 模拟取消订阅
    subject.UnSubscribe(observer1);

    // 通知订阅事件的观察者
    subject.Notify(20);

    return 0;
}